local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
local Gravity = require('scripts.controllers.Gravity')
local Map01 = require('resources.maps.Map01')
local BackgroundBG = require 'scripts.models.BackgroundBG'
local LevelFactory = require('scripts.models.LevelFactory')

local backgroundMusicChannel

scene.finished = false

function scene:updateLevelCallback()
return function(delta)
   if self.finished then
      return
   end

   if self.hasMask then return end

   if self.gameWorld.player:isAlive() == false then
      if self.finished == false then
         self.finished = true
         logger:debug('X_X')
         playerLife = playerLife - 1
         self.gameWorld:startDeath()
         if playerLife > 0 then
            timer.performWithDelay(500,
               function ()
                  storyboard.gotoScene("scripts.scenes.testScene", {effect = "fade",time = 100})
               end )
         else
            playerLife = PLAYER_NUMBER_OF_LIFES
            timer.performWithDelay(500,
               function ()
                  storyboard.gotoScene("scripts.scenes.gameover", {effect = "fade",time = 100})
               end )
         end
      end
   elseif self.gameWorld:isClear() then
      if self.finished == false then
         self.finished = true
         -- logger:debug('X_X')

         LEVEL = LEVEL + 1
         if LEVEL <= 3 then
            timer.performWithDelay(500,
               function ()
                  storyboard.gotoScene("scripts.scenes.testScene", {effect = "fade",time = 100})
               end )
         else
            storyboard.gotoScene("scripts.scenes.scoreScene", {
               effect = "fade",
               time = 100,
               params = {
                  finalScore = self.gameWorld:getTotalScore()
               }
            })
         end
      end
   else
      self.gameWorld:update(delta)
      self.background:update(delta, self.gameWorld.player.x)
      self:updateHUD(delta)
   end
end
end

function scene:updateHUD(delta)
   local timeTotal =  math.round(60*3 - self.gameWorld.time)

   self.hud.mask1Btn.cooldown = self.hud.mask1Btn.cooldown - delta
   self.hud.mask2Btn.cooldown = self.hud.mask2Btn.cooldown - delta

   if self.hud.mask1Btn.cooldown <= 0 then
      self.hud.mask1Btn:setSequence('normal')
   else
      self.hud.mask1Btn:setSequence('disabled')
   end

   if self.hud.mask2Btn.cooldown <= 0 then
      self.hud.mask2Btn:setSequence('normal')
   else
      self.hud.mask2Btn:setSequence('disabled')
   end


   if timeTotal <= 0 then
      self.gameWorld.player.life = 0
   end

   local seconds = timeTotal % 60
   if timeTotal % 60 < 10 then
      seconds = "0" .. (timeTotal % 60)
   end

   self.hud.timeText.text =  math.floor(timeTotal / 60) .. ":" .. seconds
end

function scene:createPishCloud(x,y,scale,timeScale,toBack)

   if scale == nil then scale = 1.0 end
   if timeScale == nil then timeScale = 1.0 end
   if toBack == nil then toBack = false end

   local cloud = display.newImage(self.gameWorld,'resources/sprites/pish_cloud.png',x,y)
   cloud:scale(0.5*scale,0.5*scale)
   cloud.alpha = 0.8
   local startRotation = math.random(1,180)
   cloud.rotation = startRotation

   if toBack then
      cloud:toBack()
   else
      system.vibrate()
   end

   timer.performWithDelay(
      0,
      function()
         transition.to(
            cloud,
            {
               duration = 2000 * timeScale,
               alpha=0,
               xScale=0.3*scale,
               yScale=0.3*scale,
               rotation=startRotation+10,
               onComplete=function()
                  DisplayObjectUtils.safeRemove(cloud)
               end
            }
         )
      end,
      3
   )

end

function scene:createPishCloud2(x,y)
   local cloud = display.newImage(self.gameWorld,'resources/sprites/mask_cloud1.png',x,y)
   cloud:scale(0.5,0.5)

   transition.to(
      cloud,
      {
         time=500,
         alpha=0.3,
         xScale=0.3,
         yScale=0.3,
         onComplete=function()
            DisplayObjectUtils.safeRemove(cloud)
         end
      }
   )

   local cloud2 = display.newImage(self.gameWorld,'resources/sprites/mask_cloud2.png',x,y)
   cloud2:scale(0.3,0.3)

   transition.to(
      cloud2,
      {
         time=500,
         alpha=0.3,
         xScale=0.5,
         yScale=0.5,
         onComplete=function()
            DisplayObjectUtils.safeRemove(cloud2)
         end
      }
   )

   -- if scale == nil then scale = 1.0 end
   -- if timeScale == nil then timeScale = 1.0 end
   -- if toBack == nil then toBack = false end

   -- local cloud = display.newImage(self.gameWorld,'resources/sprites/pish_cloud.png',x,y)
   -- cloud:scale(0.5*scale,0.5*scale)
   -- cloud.alpha = 0.8
   -- local startRotation = math.random(1,180)
   -- cloud.rotation = startRotation

   -- if toBack then
   --    cloud:toBack()
   -- else
   --    system.vibrate()
   -- end

   -- timer.performWithDelay(
   --    0,
   --    function()
   --       transition.to(
   --          cloud,
   --          {
   --             duration = 2000 * timeScale,
   --             alpha=0,
   --             xScale=0.3*scale,
   --             yScale=0.3*scale,
   --             rotation=startRotation+10,
   --             onComplete=function()
   --                DisplayObjectUtils.safeRemove(cloud)
   --             end
   --          }
   --       )
   --    end,
   --    3
   -- )

end

function scene:createGameObjects()
   -- level is defined in GameConstants
   -- print(LEVEL)
   local levelConfig = self:getLevel(LEVEL)
   local gameWorld = GameWorld:new(Gravity:new(), levelConfig)
   local background = BackgroundBG.new()
   local hud = display.newGroup()
   -- self.view:insert(gameWorld.player.lifeLine)


   self.gameWorld = gameWorld
   self.background = background
   self.hud = hud

   self.view:insert(background)
   self.view:insert(gameWorld)
   self.view:insert(hud)

   self:createHUD()
end

function scene:createMask1()
   local spriteSheetInfo = require('resources.sprites.atlasses.buttonsmask-hd')
   local spriteSheet     = graphics.newImageSheet("resources/sprites/atlasses/buttonsmask-hd.png", spriteSheetInfo:getSheet())
   local sequenceData = {
      { name="normal", sheet=spriteSheet, start=4, count=1, time=500, loopCount=0 },
      { name="hover", sheet=spriteSheet, start=6, count=1, time=500, loopCount=0 },
      { name="disabled", sheet=spriteSheet, start=5, count=1, time=500, loopCount=0 }
   }

   local mask1Btn = display.newSprite(self.view,spriteSheet, sequenceData )
   mask1Btn.x,mask1Btn.y = X*0.925,Y*0.2
   mask1Btn:scale(0.75,0.75)
   mask1Btn.cooldown = 0

   DisplayObjectUtils.addTapEventListener(
      mask1Btn,
      function()
         scene.gameWorld.player:setMask(BLUE_MASK)
         mask1Btn:setSequence('disabled')
         --mask1Btn.cooldown = BLUE_MASK_COOLDOWN
      end,
      'normal','hover'
   )

   self.hud:insert(mask1Btn)
   self.hud.mask1Btn = mask1Btn
end

function scene:createMask2()
   local spriteSheetInfo = require('resources.sprites.atlasses.buttonsmask-hd')
   local spriteSheet     = graphics.newImageSheet("resources/sprites/atlasses/buttonsmask-hd.png", spriteSheetInfo:getSheet())
   local sequenceData = {
      { name="normal", sheet=spriteSheet, start=1, count=1, time=500, loopCount=0 },
      { name="hover", sheet=spriteSheet, start=3, count=1, time=500, loopCount=0 },
      { name="disabled", sheet=spriteSheet, start=2, count=1, time=500, loopCount=0 }
   }

   local mask2Btn = display.newSprite(self.view,spriteSheet, sequenceData )
   mask2Btn.x,mask2Btn.y = X*0.075,Y*0.2
   mask2Btn:scale(0.75,0.75)
   mask2Btn.cooldown = 0

   DisplayObjectUtils.addTapEventListener(
      mask2Btn,
      function()
         scene.gameWorld.player:setMask(RED_MASK)
         mask2Btn:setSequence('disabled')
         --mask2Btn.cooldown = RED_MASK_COOLDOWN
      end,
      'normal','hover'
   )

   self.hud:insert(mask2Btn)
   self.hud.mask2Btn = mask2Btn
end

function scene:createPlayerLife(iter, nameImage)
   local spriteSheetInfo = require('resources.sprites.atlasses.playerlife')
   local spriteSheet     = graphics.newImageSheet("resources/sprites/atlasses/playerlife.png", spriteSheetInfo:getSheet())
   local sequenceData = {
      { name="seq1", sheet=spriteSheet, start=2, count=1, time=500, loopCount=0 },
      { name="seq2", sheet=spriteSheet, start=1, count=1, time=500, loopCount=0 }
   }
   assert(spriteSheetInfo:getFrameIndex("playerlife1"))
   local imageLife = display.newImage(spriteSheet, spriteSheetInfo:getFrameIndex(nameImage))
   imageLife.x,imageLife.y = X*0.1 * (iter / 1.5) ,Y*0.9

   imageLife:scale(0.45,0.45)

   self.hud:insert(imageLife)
end

function scene:createHUD()
   self:createMask1()
   self:createMask2()

   --Drawing player life
   for iter = 1, playerLife, 1 do
       self:createPlayerLife(iter, "playerlife2")
   end

   for iter = playerLife + 1, PLAYER_NUMBER_OF_LIFES, 1 do
       self:createPlayerLife(iter, "playerlife1")
   end


   --Game time
   local timeText = display.newText({
      text='0',
      x=X*0.5,
      y=Y*0.15,
      parent=self.view,
      font=Font.get('seagram'),
      fontSize=10
   })

   local levelName = 'TUTORIAL'
   if LEVEL > 1 then
      levelName = 'STAGE - ' .. LEVEL - 1
   end
   -- else
   self:createHints()
   -- end

   local stageLevel = display.newText({
      text=levelName,
      x=X*0.5,
      y=Y*0.1,
      parent=self.view,
      font=Font.get('seagram'),
      fontSize=10
   })


   self.hud.timeText = timeText
   self.hud.timeText:setFillColor( 1, 1, 1 )
   self.hud.timeText:toFront()
end

function scene:createHints()
   local group = display.newGroup()
   
   local bg = display.newRect(group, 0, 0, X, Y)
   bg.x, bg.y = halfX, halfY
   bg:setFillColor( 0, 0, 0, 0.5 )

   local center = display.newText({
      parent = group,
      x = halfX,
      y = 50,
      width = 100,
      align = 'center',
      text = "By wearing masks the inhabitants of the kingdom will see you as one of them and won't attack you",
      fontSize = 8,
      font = Font.get('seagram')
   })

   local arrowLeft = display.newImage(group, 'resources/sprites/arrowtuto.png' )
   arrowLeft.x, arrowLeft.y = 35, halfY - 30
   arrowLeft:scale(0.5, 0.5)
   self.view:insert(group)

   local textLeft = display.newText({
      parent = group,
      x = arrowLeft.x + 10,
      y = arrowLeft.y + 30,
      width = 70,
      text = 'Beware, this mask will mess with your controls',
      fontSize = 8,
      font = Font.get('seagram')
   })


   local arrowRight = display.newImage(group, 'resources/sprites/arrowtuto.png' )
   arrowRight.x, arrowRight.y = X - 35, halfY - 30
   arrowRight:scale(0.5, 0.5)
   self.view:insert(group)

   local textRight = display.newText({
      parent = group,
      x = arrowRight.x,
      y = arrowRight.y + 30,
      width = 70,
      text = 'Beware, this mask will drastically increase your speed',
      fontSize = 8,
      font = Font.get('seagram')
   })


   local arrowLife = display.newImage(group, 'resources/sprites/arrowtuto.png' )
   arrowLife.x, arrowLife.y = 145, Y - 30
   arrowLife:scale(0.5, 0.5)
   arrowLife.rotation = -90
   self.view:insert(group)

   local textLife = display.newText({
      parent = group,
      x = arrowLife.x + 60,
      y = arrowLife.y,
      text = "Your lives remaining",
      fontSize = 8,
      font = Font.get('seagram')
   })

   local start = display.newText({
      parent = group,
      x = halfX,
      y = halfY,
      text = "Touch to start",
      fontSize = 30,
      font = Font.get('seagram')
   })

   self.hasMask = true
   group:addEventListener( 'touch', function (e)
      -- print (e.phase)
      if e.phase == 'ended' then
         transition.to(group, { time = 1000, alpha = 0, onComplete = function (e)
            self.hasMask = false            
         end })
      end
   end )

end

function scene:getLevel(level)
   -- local rows = 5
   -- local cols = 10
   local w = 40
   local h = 40

   local levelConfig = LevelFactory:generateLevel(level)
   local structure = levelConfig.levelMapConfig
   local rows = levelConfig.rows
   local cols = levelConfig.cols
   return {
   	rows = rows,
   	cols = cols,
   	levelWidth = w,
   	levelHeight = h,
   	structure = structure,
   	start = levelConfig.start,
   	goal = levelConfig.goal,
   	knights = levelConfig.knights,
   	orcs = levelConfig.orcs
   }
end

--Methods
function scene:createScene(event)
   self.gameController = GameController:new()
   logger:gameEvent("Create Test Scene")
   storyboard.removeAll()
   self.timers = {}

   scene:createGameObjects()
end
function scene:enterScene(event)
   logger:gameEvent("Enter Test Scene")

   backgroundMusicChannel = audio.play( backgroundMusic, { channel=10, loops=-1, fadein=5000 }  )
   self.gameController:addCallback(scene:updateLevelCallback(), 'mainLoop')
   self.gameController:beginGame()
end

function scene:exitScene(event)
   logger:gameEvent("exit Test Scene")

   self.gameController:clearAllCallbacks()
   self.gameController:stop()
end

function scene:destroyScene(event)
   logger:gameEvent("destroy Test Scene")

   for i=#self.timers,1,-1 do
      timer.cancel(self.timers[i])
      table.remove(self.timers,i)
   end

   audio.stop( backgroundMusicChannel )
   self.gameController:clearAllCallbacks()
   self.gameController:stop()
end

scene:addEventListener("createScene",scene)
scene:addEventListener("enterScene",scene)
scene:addEventListener("exitScene",scene)
scene:addEventListener("destroyScene", scene)

return scene



